public class Line2D{
    
    private Point2D start;
    private Point2D end;

    private Point2D unite;
    private Point2D normal;

    private boolean UniteCalculated;
    private boolean NormalCalculated;

    public Line2D( Point2D PointA, Point2D PointB){
	this.start=PointA;
	this.end=PointB;
	this.NormalCalculated=false;
    }

    public Line2D(){
	this(0,0,0,0);
    }
   
    public Line2D( double PointAx, double PointAy, double PointBx, double PointBy ){
	this.start=new Point2D(PointAx, PointAy);
	this.end=new Point2D(PointBx, PointBy);
	this.NormalCalculated=false;
    }
    
    public void setStart(double x, double y)
    {
	this.start.setX(x);
	this.start.setX(y);
	this.UniteCalculated=false;
	this.NormalCalculated=false;
    }

    public void setStart(Point2D p)
    {
	this.start=p;
	this.UniteCalculated=false;
	this.NormalCalculated=false;
    }

    public void setEnd(double x, double y)
    {
	this.end.setX(x);
	this.end.setX(y);
	this.UniteCalculated=false;
	this.NormalCalculated=false;
    }

    public void setEnd(Point2D p)
    {
	this.end=p;
	this.UniteCalculated=false;
	this.NormalCalculated=false;
    }

    public void Calculer(){
	this.setUnite();
	this.setNormal();
    }

    public double getNorme()
    {
	return  this.start.distance(this.end);
    }

    //FIXME : RENDEZ MOI MOINS MOCHE !
    //On place SUR le vecteur le point, tel que la distance start->unite vaille 1
    public void setUnite() {

	double norme=this.getNorme();

	double distY=end.getY()-start.getY();
	double distX=end.getX()-start.getX();
	double uniteX=start.getX()+(distX/norme);
	double uniteY=start.getY()+(distY/norme);

	this.unite=new Point2D(uniteX, uniteY);
	this.UniteCalculated=true;
    }

    public Point2D getUnite(){

	if(!this.UniteCalculated)
	    this.setUnite();
	return this.unite;
    }
    /*On place le point, tel que :
           la distance start->unite vaille 1
	   Ce point soit la normale "à droite"*/
    
    public void setNormal(){
	if(!this.UniteCalculated)
	    this.setUnite();

	double x=(this.unite.getY()-this.start.getY())+start.getX();
	double y=-(this.unite.getX()-this.start.getX())+start.getY();
	this.normal=new Point2D(x,y);

	this.NormalCalculated=true;
    }

    public Point2D getNormal(){
	if(!this.NormalCalculated)
	    this.setNormal();
	return this.normal;
    }

    //CODEZ MOI !
    /*Retourne vrai si le point est à droite de la DROITE*/
    public boolean estADroite(Point2D p){
      
      double vdirx = normal.getX() - start.getX();
      double vdiry = normal.getY() - start.getY();

      double vpx = p.getX() - start.getX();
      double vpy = p.getY() - start.getY();

      
      return (vpx*vdirx + vpy*vdiry) > 0.0 ;
    }

    //CODEZ MOI !
    /*Retourne vrai si le point peut se projeter sur le SEGMENT, faux si le projeté est en dehors */
    public Point2D seProjete(Point2D p)
    {
      double vdirx = unite.getX() - start.getX();
      double vdiry = unite.getY() - start.getY();

      double vpx = p.getX() - start.getX();
      double vpy = p.getY() - start.getY();

      double dot = vpx*vdirx + vpy*vdiry;

      if (!(dot >= 0.0 && dot <= getNorme()))
	return null;

      //else
      return new Point2D(start.getX() + vdirx*dot,
			 start.getY() + vdiry*dot);

    }

    //CODEZ MOI !
    //Retourne la distance de ce point par rapport à son projeté sur le segment
    public double Distance(Point2D p)
    {
	return 1;
    }

    //CODEZ MOI !
    //Retourne le point2D ( fabriqué) d'intersection des deux SEGMENTS, null si cette intersection n'existe pas !
    public Point2D intersection(Line2D l)
    {
	return new Point2D(1,1);
    }

    //CODEZ MOI !
    //Retourne le point2D (référence, pointeur ) si deux lignes partagent le meme point, null sinon.
    public Point2D touche(Line2D l)
    {
	return new Point2D(1,1);
    }

    public String toString(){
	return start+"->"+end;
    }

    public static void main(String []argv){

	Point2D end = new Point2D(0,8);
	Point2D start = new Point2D(0,0);

	Line2D line=new Line2D(start, end);

	System.out.println(line);
	System.out.println("Vecteur unite : "+line.getUnite());
	System.out.println("Normale : "+line.getNormal());


	Point2D proj = new Point2D(3,8);
	System.out.println("est a droite ? : "+(line.estADroite(proj) ? "oui":"non"));
	System.out.println("point de projection : "+line.seProjete(proj));
    }

	

}

    